-- Radical by Basil Voronkov
-- Module 'navigation'
---------------------------------------------
-- This module is responsible for on screen navigation
-- using up/down/left/right arrows displayed in the
-- right corner of the screen.
require "lib/core"
require "lib/drawing"
--require "lib/popup"

navigation = {
  navwidth = 57,
  navheight = 58
}

function vw(dsc, way)
  return {
     dsc        = dsc
    ,way        = way
    ,noway      = function(s,err)
                    s.cnd_ = "false";
                    s.err_ = err;
                    return s;
                  end
    ,cnd        = function(s,cnd,err)
                    s.cnd_ = cnd;
                    s.err_ = err;
                    return s;
                  end
    ,snd        = function(s,snd)
                    s.snd_ = snd;
                    return s;
                  end
    ,sndif      = function(s,snd,cnd)
                    s.snd_ = snd;
                    s.sndcnd_ = cnd;
                    return s;
                  end
  }
end

function navigation.steps()
  if _navsteps == nil then
    _navsteps = 0;
  end
  return _navsteps;
end

function navigation.reset()
  _navsteps = 0;
end

function navigation.room(o)
  local ondrawbg = o.ondrawbg;
  local ontimer = o.ontimer;
  local onclick = o.onclick;
  
  if navigation.arrows == nil then
    navigation.arrows = { 
      ["up"] = { 20, 4, 18, 9 },
      ["down"] = { 20, 44, 18, 9 },
      ["left"] = { 5, 19, 9, 18 },
      ["right"] = { 43, 19, 9, 18 }
    };
  end
  
  if navigation.map == nil then
    navigation.map = map(const.hudx, 
      const.hudy + const.blackbar,
      navigation.navwidth, navigation.navheight);
    for i,v in pairs(navigation.arrows) do
      navigation.map:add(i, v[1], v[2], v[3], v[4]);
    end
  end
  
  local function clean(pic, last)
    if last ~= nil then
      drawing.clean(pic, last[1], last[2], last[3], last[4]);
    end
  end
  
  local function walk_dest(dest)
    here().showitem = nil;
    if dest.cnd_ == nil or apply(dest.cnd_) then
      if _navsteps == nil then
        _navsteps = 0;
      end
      _navsteps = _navsteps + 1;
      if dest.snd_ ~= nil and (dest.sndcnd_ == nil or apply(dest.sndcnd_)) then
        play_sound(dest.snd_);
      end
      here().tmpdsc = nil;
      if is_function(dest.way) then
        rcall(dest.way);
      elseif dest.fast then
        ref(dest.way).tmpdsc = nil;
        walk(dest.way);
      else
        ref(dest.way).tmpdsc = nil;
        walk(dest.way);
      end
    else
      if dest.snd_ ~= nil and (dest.sndcnd_ == nil or apply(dest.sndcnd_)) then
        play_sound(dest.snd_);
      else
        play_sound("not");
      end
      here().tmpdsc = rcall(dest.err_,dest);
      refresh();
    end
  end
  
  o.ondrawbg    = function(s, pic)
                    if ondrawbg ~= nil then
                      ondrawbg(s, pic);
                    end
                    if s.nav ~= nil then
                      local x,y = const.hudx,const.hudy;
                      local bw = sprite.box(navigation.navwidth+2, navigation.navheight+2, const.textcolor);
                      sprite.copy(bw, pic, x-1, y-1);
                      sprite.free(bw);
                      local bb = sprite.box(navigation.navwidth, navigation.navheight, "black");
                      sprite.copy(bb, pic, x, y);
                      sprite.free(bb);
                      for i,v in pairs(navigation.arrows) do
                        drawing.draw_arrow(s.nav, pic, i, x+v[1], y+v[2]);
                      end
                    end
                    return pic;
                  end
  o.ontimer     = function(s, x, y)
                    if ontimer ~= nil then
                      ontimer(s, x, y);
                    end
                    if s.nav ~= nil then
                      local sel = navigation.map:get(x, y);
                      local nx,ny = const.hudx,const.hudy-20;
                      if s.oldsel_ ~= sel then
                        if s.last_ ~= nil then
                          clean(s.pic, s.last_);
                          s.last_ = nil;
                        end
                        if s.lasthint_ ~= nil then
                          clean(s.pic, s.lasthint_);
                          s.lasthint_ = nil;
                        end
                      end
                      if s.oldsel_ ~= sel then
                        local arr = navigation.arrows[sel];
                        if arr ~= nil and s.nav[sel] ~= nil then
                          local hy = ny;
                          if sel == "right" or sel == "left" then
                            hy = hy+19;
                          elseif sel == "down" then
                            hy = hy+40;
                          end
                          drawing.copy_arrow(s.nav, s.pic, sel, nx+arr[1], ny+arr[2], true);
                          s.last_ = { nx+arr[1], ny+arr[2], arr[3], arr[4] };
                          s.oldsel_ = sel;
                          if s.nav[sel].dsc ~= "" then
                            local mw = drawing.textframe(s.pic, s.nav[sel].dsc, nx-10, hy, 4, 2, true);
                            s.lasthint_ = { nx-mw-10, hy, mw, 25 };
                          end
                        else
                          s.oldsel_ = nil;
                        end
                      end
                    end
                  end
  o.onclick     = function(s, x, y)
                    if onclick ~= nil then
                      onclick(s, x, y);
                    end
                    local sel = navigation.map:get(x, y);
                    if s.nav ~= nil and sel ~= nil and s.nav[sel] ~= nil then
                      clean(s.pic, s.last_);
                      clean(s.pic, s.lasthint_);
                      s.oldsel_ = nil;
                      s.last_ = nil;
                      s.lasthint_ = nil;
                      walk_dest(s.nav[sel]);
                    end
                  end
  return o;
end